﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using System.Windows.Input;
using GameEngine;
using GameBoardViewer.Animation;
using Win = System.Windows;
using GameBoardViewer.Common;



namespace GameBoardViewer.Board3D
{
    public class GameBoardModel : IBoard3DControl
    {
        protected IBoard3D _board3D;
        protected Game _game = null;
        protected SpriteBatch spriteBatch;
        protected GameManager m_GameManager;
        private AnimationBlock animBlock;

        Model m_BoardModel;
        Model m_ManModel;
        Model m_KingModel;
        Texture2D m_BoardTexture;
        Texture2D m_WhiteMan;
        Texture2D m_WhiteManSel;
        Texture2D m_BlackMan;
        Texture2D m_BlackManSel;
        Texture2D m_WhiteKing;
        Texture2D m_WhiteKingSel;
        Texture2D m_BlackKing;
        Texture2D m_BlackKingSel;

        Texture2D m_FieldHighlightTexture;
        Texture2D m_FieldToMoveTexture;
        Texture2D m_DropFieldTexture;
        RenderTarget2D _RenderTarget;

        BoundingBox m_BoardBoudingBox;
        Matrix m_BoardProjection;
        Matrix m_BoardView;
        Matrix m_BoardWorld;

        AnimationParams _animationParams;
        RotationBoardAnimation m_RotationBoardAnimation;

        List<Position> _fieldsToMove;

        public event EventHandler RenderBackgroundEvent;

        #region Board Rotation And Zoom

        // mouse 
        int m_iMouseScrollWheel;
        int m_iLastMouseY;
        int m_iLastMouseX;
        // ButtonState m_LeftButtonState;
        // ButtonState m_RightButtonState;


        // rotation
        float m_fRotationXStep = (float)Math.PI / 20f;
        float m_fRotationX = 0;
        float m_fRotationYStep = (float)Math.PI / 20f;
        float m_fRotationY = (float)Math.PI;
        bool _bRotatingBoard;

        int m_iMouseYThreshold = 1;
        int m_iMouseXThreshold = 1;

        // scaling
        float m_Scale = 0.35f;
        float m_ManScale = 0.08f;
        float m_MinScale = 0.3f;
        float m_MaxScale = 1f;
        int m_iScaleIndex = 13;
        float m_ScaleStep = 0.05f;
        
        int m_MouseOnRow = 0;
        int m_MouseOnCol = 0;
        int m_HighlightFigureRow = -1;
        int m_HighlightFigureCol = -1;
        int m_DragFigureRow = -1;
        int m_DragFigureCol = -1;
        Vector3 m_DragFigurePosition;
        int m_DropFieldRow = -1;
        int m_DropFieldCol = -1;


        #endregion


        public GameBoardModel(Game game, IBoard3D board3D)
        {
            _board3D = board3D;
            _game = game;
            _animationParams = new AnimationParams();
            _fieldsToMove = new List<Position>();
            //m_LeftButtonState = ButtonState.Released;
            //m_RightButtonState = ButtonState.Released;
            _bRotatingBoard = false;
            m_fRotationX = (float)(Math.PI / 4);
            m_fRotationY = (float)Math.PI;
            animBlock = null;
        }

        public void SetData(GameManager _gameManager)
        {
            m_GameManager = _gameManager;
        }

        public void Initialize()
        {
        }

        public void LoadContent()
        {
            spriteBatch = new SpriteBatch(_game.GraphicsDevice);

            // initialize mouse
            m_iMouseScrollWheel = Microsoft.Xna.Framework.Input.Mouse.GetState().ScrollWheelValue;
            m_iLastMouseY = Microsoft.Xna.Framework.Input.Mouse.GetState().Y;
            m_iLastMouseX = Microsoft.Xna.Framework.Input.Mouse.GetState().X;

            // load data
            m_BoardModel = _game.Content.Load<Model>("sachovnice");
            m_BoardTexture = _game.Content.Load<Texture2D>("board8x8");
            m_ManModel = _game.Content.Load<Model>("kamen");
            m_KingModel = _game.Content.Load<Model>("dama");
            m_WhiteMan = _game.Content.Load<Texture2D>("kamen.white");
            m_WhiteManSel = _game.Content.Load<Texture2D>("kamen.white.selection");
            m_BlackMan = _game.Content.Load<Texture2D>("kamen.black");
            m_BlackManSel = _game.Content.Load<Texture2D>("kamen.black.selection");
            m_WhiteKing = _game.Content.Load<Texture2D>("dama.white");
            m_WhiteKingSel = _game.Content.Load<Texture2D>("dama.white.selection");
            m_BlackKing = _game.Content.Load<Texture2D>("dama.black");
            m_BlackKingSel = _game.Content.Load<Texture2D>("dama.black.selection");

            m_BoardBoudingBox = MeshHelper.CalculateBoundingBox(m_BoardModel);
            _RenderTarget = new RenderTarget2D(_game.GraphicsDevice, m_BoardTexture.Width, m_BoardTexture.Height);


            // initialize textures
            m_FieldHighlightTexture = new Texture2D(_game.GraphicsDevice, 1, 1);
            Color[] data = new Color[1];           
            m_FieldHighlightTexture.GetData<Color>(data);
            data[0] = new Color(255, 0, 0, 128);
            m_FieldHighlightTexture.SetData<Color>(data);
            
            m_FieldToMoveTexture = new Texture2D(_game.GraphicsDevice, 1, 1);
            data = new Color[1];
            m_FieldToMoveTexture.GetData<Color>(data);
            data[0] = new Color(255,255,0,128);
            m_FieldToMoveTexture.SetData<Color>(data);

            m_DropFieldTexture = new Texture2D(_game.GraphicsDevice, 1, 1);
            data = new Color[1];
            m_DropFieldTexture.GetData<Color>(data);
            data[0] = new Color(0, 0, 255, 128);
            m_DropFieldTexture.SetData<Color>(data);
        }

        public bool  Update(MouseState mouse)
        {
            if (m_RotationBoardAnimation != null)
            {
                m_RotationBoardAnimation.GetRotationParameters(out m_fRotationX, out m_fRotationY);
                if (m_RotationBoardAnimation.Finished)
                    m_RotationBoardAnimation = null;
                return true;
            }

            if (animBlock != null)
            {
                animBlock.UpdateAnimation();
                if (animBlock.Finished)
                {
                    _animationParams.Clear();
                    animBlock = null;
                    m_GameManager.MoveHistory.MoveForward();
                }
            }


            UpdateZoom(mouse);

            return false;
        }

        public void Draw()
        {
            RenderGameBoard();
            RenderFigures();
        }

        internal AnimationBlock ComposeAnimation(Move completeMove)
        {
            AnimationBlock animBlock = new AnimationBlock();
            Move move = completeMove;
            Position figurePos = move.startPos;
            while (move != null)
            {
                int animLength = 500 * Math.Abs(move.endPos.Row - move.startPos.Row);

                if (move.RemovingFigure == true)
                {
                    animBlock.AddAnimation(new JumpMoveAnimation(figurePos,
                        GetFigurePosition(move.startPos.Row, move.startPos.Col),
                        GetFigurePosition(move.endPos.Row, move.endPos.Col),
                        TimeSpan.FromMilliseconds(animLength)));

                    animBlock.AddAnimation(new JumpedFigureAnimation(move.removedFigurePlace,
                            TimeSpan.FromMilliseconds(500)));
                }
                else
                {
                    animBlock.AddAnimation(new SlideMoveAnimation(figurePos,
                        GetFigurePosition(move.startPos.Row, move.startPos.Col),
                        GetFigurePosition(move.endPos.Row, move.endPos.Col),
                        TimeSpan.FromMilliseconds(animLength)));
                }


                move = move.nextMove;
            }

            return animBlock;
        }

        public void DoBoardRotation(float finishXRotation, float finishYRotation)
        {
            if(Math.Abs(finishYRotation - 0) < 0.0001)
            {
                finishYRotation = m_fRotationY > (float)Math.PI ? (float)Math.PI * 2 : 0f;
            }


            m_RotationBoardAnimation = new RotationBoardAnimation(m_fRotationX, finishXRotation,
                                        m_fRotationY, finishYRotation, TimeSpan.FromMilliseconds(700));

            m_RotationBoardAnimation.StartAnimation();
        }
        
        public void AnimateMove(Move move)
        {
            animBlock = ComposeAnimation(move);

            animBlock.AnimationEvent += (figurePos, position, alpha, point) =>
                    {
                        if (position == Vector3.Zero)
                            _animationParams.SetAlphaColor(figurePos, alpha);
                        else
                            _animationParams.SetPosition(figurePos, position);
                    };

            
            animBlock.StartAnimation();
        }

        #region Render Methods

        protected Texture2D PrepareDynamicBoardTexture()
        {
            // draw to board texture
            _game.GraphicsDevice.SetRenderTarget(_RenderTarget);
            spriteBatch.Begin();
            spriteBatch.Draw(m_BoardTexture, new Rectangle(0, 0, m_BoardTexture.Width, m_BoardTexture.Height), Color.White);

            if (m_MouseOnCol != -1 && m_MouseOnRow != -1)
            {
                Rectangle rect = GetRectangleForPosition(m_MouseOnRow, m_MouseOnCol);
                spriteBatch.Draw(m_FieldHighlightTexture, rect, Color.Silver);
            }

            foreach (var position in _fieldsToMove)
            {
                Rectangle rect = GetRectangleForPosition(position.Row, position.Col);
                spriteBatch.Draw(m_FieldToMoveTexture, rect, Color.White);
            }

            if (m_DropFieldRow != -1 && m_DropFieldCol != -1)
            {
                Rectangle rect = GetRectangleForPosition(m_DropFieldRow, m_DropFieldCol);
                spriteBatch.Draw(m_DropFieldTexture, rect, Color.White);
            }

            spriteBatch.End();

            _game.GraphicsDevice.SetRenderTarget(null);
            return _RenderTarget;
        }

        protected void RenderGameBoard()
        {
            Texture2D dynamicTexture = PrepareDynamicBoardTexture();

            this._game.GraphicsDevice.DepthStencilState = DepthStencilState.Default;
            _game.GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, new Color(236, 236, 236), 100.0f, 0);

            if (RenderBackgroundEvent != null)
            {
                RenderBackgroundEvent(this, EventArgs.Empty);               
            }
            
            foreach (ModelMesh mesh in m_BoardModel.Meshes)
            {
                foreach (BasicEffect effect in mesh.Effects)
                {
                    float scale = m_MinScale + m_ScaleStep * m_iScaleIndex;
                    effect.EnableDefaultLighting();
                    effect.LightingEnabled = true;
                    effect.DirectionalLight0.Direction = new Vector3(1, 1, 1);
                    Vector3 clrVector = Color.White.ToVector3();
                    effect.DirectionalLight0.DiffuseColor = clrVector;

                    effect.DirectionalLight1.Direction = Vector3.Down;
                    effect.DirectionalLight1.DiffuseColor = Color.White.ToVector3();


                    Vector3 yAxisRotation = Vector3.Forward;
                    yAxisRotation = Vector3.Transform(yAxisRotation, Matrix.CreateRotationX(m_fRotationX));
                    m_BoardWorld = Matrix.CreateScale(m_Scale) * Matrix.CreateRotationX(-(float)(1 * Math.PI / 2)) *
                                Matrix.CreateScale(scale)
                            * Matrix.CreateRotationX(m_fRotationX) * Matrix.CreateFromAxisAngle(yAxisRotation, m_fRotationY);
                    effect.World = m_BoardWorld;
                    m_BoardView = Matrix.CreateLookAt(new Vector3(0, 0, -50), Vector3.Forward, Vector3.Up);
                    effect.View = m_BoardView;
                    m_BoardProjection = Matrix.CreatePerspectiveFieldOfView(
                        MathHelper.ToRadians(45.0f), _game.GraphicsDevice.Viewport.AspectRatio,
                        1.0f, 10000.0f);

                    effect.Projection = m_BoardProjection;
                    effect.TextureEnabled = true;
                    effect.Texture = dynamicTexture;
                }


                mesh.Draw();
            }
        }

        protected void RenderFigures()
        {
            if (m_GameManager == null)
                return;

            this._game.GraphicsDevice.DepthStencilState = DepthStencilState.Default;

            for (int row = 0; row < 8; row++)
            {
                for (int col = 0; col < 8; col++)
                {
                    enumFigureType figureType = m_GameManager.GameBoard.GetField(row, col);
                    if (figureType == enumFigureType.Nothing)
                        continue;


                    Model pieceModel = figureType.IsKing() == false ? m_ManModel : m_KingModel;
                    Texture2D pieceTexture;
                    if(figureType.IsKing() == false)
                    {
                        if (figureType.FigureColor() == enumFigureColor.White)
                        {
                            if (row == m_HighlightFigureRow && col == m_HighlightFigureCol)
                                pieceTexture = m_WhiteManSel;
                            else
                                pieceTexture = m_WhiteMan;
                        }
                        else
                        {
                            if (row == m_HighlightFigureRow && col == m_HighlightFigureCol)
                                pieceTexture = m_BlackManSel;
                            else
                                pieceTexture = m_BlackMan;
                        }
                    }
                    else
                    {
                        if (figureType.FigureColor() == enumFigureColor.White)
                        {
                            if (row == m_HighlightFigureRow && col == m_HighlightFigureCol)
                                pieceTexture = m_WhiteKingSel;
                            else
                                pieceTexture = m_WhiteKing;
                        }
                        else
                        {
                            if (row == m_HighlightFigureRow && col == m_HighlightFigureCol)
                                pieceTexture = m_BlackKingSel;
                            else
                                pieceTexture = m_BlackKing;
                        }
                    }

                    foreach (ModelMesh mesh in pieceModel.Meshes)
                    {
                        foreach (BasicEffect effect in mesh.Effects)
                        {
                            float scale = m_MinScale + m_ScaleStep * m_iScaleIndex;
                            effect.EnableDefaultLighting();
                            effect.LightingEnabled = true;
                            Vector3 dir = new Vector3(-1f, 1f, -1f);
                            dir.Normalize();
                            effect.AmbientLightColor = Color.White.ToVector3();
                            effect.DirectionalLight0.Direction = dir;
                            effect.DirectionalLight0.DiffuseColor = Color.White.ToVector3();
                            effect.DirectionalLight0.SpecularColor = Color.White.ToVector3();
                            dir = new Vector3(0, 0, 1);
                            dir.Normalize();
                            effect.DirectionalLight1.Direction = Vector3.Forward;
                            effect.DirectionalLight1.DiffuseColor = Color.White.ToVector3();
                            effect.DirectionalLight1.SpecularColor = Color.White.ToVector3();

                            effect.Alpha = _animationParams.GetAlphaColor(new Position(row, col));

                            float X = 0;
                            float Y = 0;
                            float Z = 0;
                            GetFigureAnimPosition(row, col, out X, out Y, out Z);
                            Matrix figureTranslation = Matrix.CreateTranslation(X, Y, Z);

                            Vector3 yAxisRotation = Vector3.Forward;
                            yAxisRotation = Vector3.Transform(yAxisRotation, Matrix.CreateRotationX(m_fRotationX));
                            effect.World = Matrix.CreateScale(m_ManScale) 
                                    * figureTranslation
                                    * Matrix.CreateScale(scale) 
                                    * Matrix.CreateRotationX(m_fRotationX) 
                                    * Matrix.CreateFromAxisAngle(yAxisRotation, m_fRotationY);

                            effect.View = Matrix.CreateLookAt(new Vector3(0, 0, -50),
                                Vector3.Forward, Vector3.Up);
                            effect.Projection = Matrix.CreatePerspectiveFieldOfView(
                                MathHelper.ToRadians(45.0f), _game.GraphicsDevice.Viewport.AspectRatio,
                                1.0f, 10000.0f);

                            effect.TextureEnabled = true;
                            effect.Texture = pieceTexture;
                        }


                        mesh.Draw();
                    }
                }
            }
        }


        #endregion

        #region Update Methods

        protected void UpdateRotation(Point point, enumButtonEvent buttonEvent)
        {
            if (buttonEvent == enumButtonEvent.LeftPressed)
            {
                _board3D.SetCapture(this);
                _bRotatingBoard = true;               
            }
            if (buttonEvent == enumButtonEvent.LeftReleased)
            {
                _board3D.ReleaseCapture();
                _bRotatingBoard = false;
            }

            if (_bRotatingBoard == true) 
            {

                if (Math.Abs(point.Y - m_iLastMouseY) > m_iMouseYThreshold)
                {
                    if (point.Y > m_iLastMouseY)
                    {
                        m_fRotationX -= m_fRotationXStep;
                        if (m_fRotationX < 0)
                            m_fRotationX = (float)0;
                    }
                    else
                    {
                        m_fRotationX += m_fRotationXStep;
                        if (m_fRotationX > ((Math.PI / 2)))
                            m_fRotationX = (float)Math.PI / 2f;

                    }

                    m_iLastMouseY = point.Y;
                }

                if (Math.Abs(point.X - m_iLastMouseX) > m_iMouseXThreshold)
                {
                    if (point.X > m_iLastMouseX)
                    {
                        m_fRotationY -= m_fRotationYStep;
                        if (m_fRotationY < 0)
                            m_fRotationY += (float)Math.PI * 2f;
                    }
                    else
                    {
                        m_fRotationY += m_fRotationYStep;
                        if (m_fRotationY > ((Math.PI * 2)))
                            m_fRotationY -= (float)Math.PI * 2f;

                    }

                    m_iLastMouseX = point.X;
                }
            }
        }

        protected void UpdateEditMode(Point point, enumButtonEvent buttonEvent)
        {
            Vector3 collisionVector = Vector3.Zero;
            int subX = point.X;
            int subY = point.Y;

            Point mousePoint = Point.Zero;
            mousePoint = RayTracer.MouseCoordinatesToTextureCoordinates(subX, subY, m_BoardModel, m_BoardProjection, m_BoardView,
                                        m_BoardWorld, m_BoardTexture, _game.GraphicsDevice.Viewport, ref collisionVector);

            if (mousePoint != Point.Zero)
            {
                int row;
                int col;
                FindFieldByCoordinates(mousePoint, out row, out col);

                if (row != -1 && col != -1)
                {
                    if (buttonEvent == enumButtonEvent.LeftReleased)
                    {
                        _board3D.ClickOnField(new Position(row, col), true);
                    }
                    if (buttonEvent == enumButtonEvent.RightReleased)
                    {
                        _board3D.ClickOnField(new Position(row, col), false);
                    }
                }
            }
        }


        protected void UpdateDragAndDrop(Point point, enumButtonEvent buttonEvent)
        {

            if (buttonEvent == enumButtonEvent.LeftReleased)
            {
                _board3D.ReleaseCapture();

                Position startPos = new Position(m_DragFigureRow, m_DragFigureCol);
                Position endPos = new Position(m_DropFieldRow, m_DropFieldCol);
                if (startPos != Position.Empty && endPos != Position.Empty)
                {
                    if (m_GameManager.CanFigureMoveHere(startPos, endPos) == true)
                    {
                        Move move = m_GameManager.CompleteMoveStep(startPos, endPos);
                        m_GameManager.DoMoveStep(move);
                        _board3D.AddMove(move);
                    }
                }

                m_DragFigureRow = m_DragFigureCol = -1;
                m_DropFieldRow = m_DropFieldCol = -1;

                return;
            }

            m_DropFieldRow = m_DropFieldCol = -1;

            if (m_DragFigureRow == -1 || m_DragFigureCol == -1)
                return;

            Vector3 collisionVector = Vector3.Zero;
            int subX = point.X;
            int subY = point.Y;

            Point mousePoint = Point.Zero;
            mousePoint= RayTracer.MouseCoordinatesToTextureCoordinates(subX, subY, m_BoardModel, m_BoardProjection, m_BoardView,
                                        m_BoardWorld, m_BoardTexture, _game.GraphicsDevice.Viewport, ref collisionVector);
            collisionVector = Vector3.Transform(collisionVector, Matrix.CreateScale(m_Scale) * Matrix.CreateRotationX(-(float)(Math.PI / 2)));
            collisionVector.Z = -2f;

            Model pieceModel = m_GameManager.GameBoard.GetField(m_DragFigureRow, m_DragFigureCol).IsKing() == false
                ? m_ManModel : m_KingModel;
            
            BoundingBox m_ManBB = MeshHelper.CalculateBoundingBox(pieceModel);
            Vector3 max = m_ManBB.Max;
            Vector3 min = m_ManBB.Min;
            max = Vector3.Transform(max, Matrix.CreateScale(m_ManScale));
            min = Vector3.Transform(min, Matrix.CreateScale(m_ManScale));
            float sizeX = max.X - min.X;
            float sizeY = max.Y - min.Y;
            collisionVector.X -= sizeX / 2;
            //collisionVector.Y -= sizeY / 2;

            m_DragFigurePosition = collisionVector;

            if (mousePoint != Point.Zero)
            {
                int row;
                int col;
                FindFieldByCoordinates(mousePoint, out row, out col);

                if (m_GameManager.CanFigureMoveHere(new Position(m_DragFigureRow, m_DragFigureCol),
                                                    new Position(row, col)) == true)
                {
                    m_DropFieldRow = row;
                    m_DropFieldCol = col;
                }
            }
        }

        protected void UpdateMouseHover(Point mousePoint, enumButtonEvent buttonEvent)
        {
            _fieldsToMove.Clear();
            if (m_DragFigureRow != -1)
                return;

            m_HighlightFigureCol = m_HighlightFigureRow = -1;

            Vector3 collisionVector = Vector3.Zero;
            Microsoft.Xna.Framework.Point point = RayTracer.MouseCoordinatesToTextureCoordinates(mousePoint.X, mousePoint.Y,
                                    m_BoardModel, m_BoardProjection, m_BoardView, m_BoardWorld, m_BoardTexture, 
                                        _game.GraphicsDevice.Viewport, ref collisionVector);
            if (point != Microsoft.Xna.Framework.Point.Zero)
            {
                
                if (buttonEvent == enumButtonEvent.RightReleased)
                {
                    //Win.MessageBox.Show(string.Format("[{0}, {1}]", point.X, point.Y));
                }
                 

                FindFieldByCoordinates(point, out m_MouseOnRow, out m_MouseOnCol);

                if(m_MouseOnRow != -1 && m_MouseOnCol != -1)
                {
                    if (m_GameManager != null && _board3D.InEditMode == false)
                    {
                        enumFigureType figureType = m_GameManager.GameBoard.GetField(m_MouseOnRow, m_MouseOnCol);
                        if (figureType != enumFigureType.Nothing)
                        {
                            if (figureType.FigureColor() == m_GameManager.GameBoard.OnMove)
                            {
                                m_GameManager.GetFigureMoves(
                                        new Position(m_MouseOnRow, m_MouseOnCol),
                                        _fieldsToMove);
                                if (_fieldsToMove.Count > 0)
                                {
                                    m_HighlightFigureRow = m_MouseOnRow;
                                    m_HighlightFigureCol = m_MouseOnCol;

                                    if (buttonEvent == enumButtonEvent.LeftPressed)
                                    {
                                        m_DragFigureRow = m_MouseOnRow;
                                        m_DragFigureCol = m_MouseOnCol;
                                        _board3D.SetCapture(this);
                                    }
                                }
                            }
                        }
                                            
                    }

                }

                /*if (mouse.RightButton == ButtonState.Pressed)
                {
                    MessageBox.Show(string.Format("[{0},{1}]", point.X, point.Y));
                }*/
            }
            else
            {
                m_MouseOnCol = -1;
                m_MouseOnRow = -1;
            }
        }

        protected void UpdateZoom(MouseState mouse)
        {
            int iScrollWheelView = mouse.ScrollWheelValue;
            if (iScrollWheelView > m_iMouseScrollWheel)
            {
                m_iScaleIndex++;
                float scale = m_MinScale + m_ScaleStep * m_iScaleIndex;
                if (scale > m_MaxScale)
                    m_iScaleIndex--;


            }
            else if (iScrollWheelView < m_iMouseScrollWheel)
            {
                m_iScaleIndex--;
                float scale = m_MinScale + m_ScaleStep * m_iScaleIndex;
                if (scale < m_MinScale)
                    m_iScaleIndex++;
            }

            m_iMouseScrollWheel = iScrollWheelView;
        }

        #endregion


        #region Computation Helper Methods

        void GetFigureAnimPosition(int row, int col, out float X, out float Y, out float Z)
        {
            X = 0;
            Y = 0;
            Z = 0;

            Vector3 pos;
            if(_animationParams.GetPositionVector(new Position(row, col), out pos) == true)
            {
                X = pos.X;
                Y = pos.Y;
                Z = pos.Z;

                return;
            }

            if (row == m_DragFigureRow && col == m_DragFigureCol)
            {
                X = m_DragFigurePosition.X;
                Y = m_DragFigurePosition.Y;
                Z = m_DragFigurePosition.Z;
                return;
            }


            GetFigurePosition(row, col, out X, out Y, out Z);
        }

        Vector3 GetFigurePosition(int row, int col)
        {
            float X = 0;
            float Y = 0;
            float Z = 0;

            GetFigurePosition(row, col, out X, out Y, out Z);

            return new Vector3(X, Y, Z);                           
        }

        void GetFigurePosition(int row, int col, out float X, out float Y, out float Z)
        {
            X = 0;
            Y = 0;
            Z = -0.8f;
            float paddingRow = 31.8f;
            float paddingCol = 34.0f;
            float Xmove = -16.5f;
            float Ymove = -13.7f;

            row = 7 - row;


            float sizeX = m_BoardBoudingBox.Max.X - m_BoardBoudingBox.Min.X;
            float sizeY = m_BoardBoudingBox.Max.Z - m_BoardBoudingBox.Min.Z;

            sizeX -= 2 * paddingCol;
            sizeY -= 2 * paddingRow;

            float fieldSizeX = sizeX / 8;
            float fieldSizeY = sizeY / 8;

            X = col * fieldSizeX + fieldSizeX / 2;
            Y = row * fieldSizeY + fieldSizeY / 2;

            X += Xmove;
            Y += Ymove;
        }

        protected bool FindFieldByCoordinates(Microsoft.Xna.Framework.Point mousePoint, out int row, out int col)
        {
            row = -1;
            col = -1;

            for (int r = 0; r < 8; r++)
                for (int c = 0; c < 8; c++)
                {
                    //if ((r + c) % 2 == 0)
                    {
                        Rectangle rect = GetRectangleForPosition(r, c);
                        if (rect.Contains(mousePoint) == true)
                        {
                            row = r;
                            col = c;
                            return true;
                        }
                    } // if
                } // for
            return false;
        }

        protected Microsoft.Xna.Framework.Rectangle GetRectangleForPosition(int row, int col)
        {
            const int margin = 70;
            int fieldSize = (m_BoardTexture.Width - margin * 2) / 8;
            Rectangle rect = new Rectangle(col * fieldSize + margin, (7 - row) * fieldSize + margin, fieldSize, fieldSize);
            return rect;
        }

        #endregion


        public void OnLButtonDown(Point point)
        {
            if (_board3D.RotationChecked == false)
            {
                UpdateMouseHover(point, enumButtonEvent.LeftPressed);
            }
            else
            {
                UpdateRotation(point, enumButtonEvent.LeftPressed);
            }
        }

        public void OnLButtonUp(Point point)
        {
            if (_board3D.RotationChecked == false)
            {
                if (_board3D.InEditMode == true)
                {
                    UpdateEditMode(point, enumButtonEvent.LeftReleased);
                }
                else
                {
                    UpdateDragAndDrop(point, enumButtonEvent.LeftReleased);
                }
            }
            else
            {
                UpdateRotation(point, enumButtonEvent.LeftReleased);
            }
        }

        public void OnMouseMoving(Point point)
        {
            if (_board3D.RotationChecked == false)
            {
                UpdateMouseHover(point, enumButtonEvent.Nothing);
                if (_board3D.InEditMode == false)
                {
                    UpdateDragAndDrop(point, enumButtonEvent.Nothing);
                }
            }
            else
            {
                UpdateRotation(point, enumButtonEvent.Nothing);
            }
        }

        public void OnRButtonDown(Point point)
        {
        }

        public void OnRButtonUp(Point point)
        {
            if (_board3D.RotationChecked == false)
            {
                if (_board3D.InEditMode == true)
                {
                    UpdateEditMode(point, enumButtonEvent.RightReleased);
                }
                else
                {
                    UpdateMouseHover(point, enumButtonEvent.RightReleased);
                }
            }
        }
    }
}
